u, v = var('u v')
d = vector([sin(u), cos(u), 0])
show(d)
parametric_plot3d(d, (u, -pi, pi/2))
Ojo todas las graficas que generó esta hoja se pueden mover para cambiar la vista, solo hay que dar click y arrastrar
e = vector([0,0,1])
r = e*sin(v)+d*cos(v)
show(r)
parametric_plot3d(2*d+0.5*r, (u, -pi, pi),(v,-pi, pi))
Ahora con colores
def pinta(u,v): return (1-cos(u+v))/2
parametric_plot3d(2*d+0.5*r, (u, -pi, pi),(v,-pi, pi),
color=(pinta,colormaps.cubehelix),
plot_points=[120,120])
Se puede crear una coloración como dice en el manual de matplotlib
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.colors import ListedColormap, LinearSegmentedColormap
??cm.get_cmap
Signature: cm.get_cmap(name=None, lut=None) Docstring: Get a colormap instance, defaulting to rc values if *name* is None. Colormaps added with "register_cmap()" take precedence over built- in colormaps. Currently, this returns the global colormap object, which is deprecated. In Matplotlib 3.5, you will no longer be able to modify the global colormaps in-place. name : matplotlib.colors.Colormap or str or None, default: None If a .Colormap instance, it will be returned. Otherwise, the name of a colormap known to Matplotlib, which will be resampled by *lut*. The default, None, means >>:rc:`image.cmap`<<. lut : int or None, default: None If *name* is not already a Colormap instance and *lut* is not None, the colormap will be resampled to have *lut* entries in the lookup table. Source: def get_cmap(name=None, lut=None): """ Get a colormap instance, defaulting to rc values if *name* is None. Colormaps added with :func:`register_cmap` take precedence over built-in colormaps. Notes ----- Currently, this returns the global colormap object, which is deprecated. In Matplotlib 3.5, you will no longer be able to modify the global colormaps in-place. Parameters ---------- name : `matplotlib.colors.Colormap` or str or None, default: None If a `.Colormap` instance, it will be returned. Otherwise, the name of a colormap known to Matplotlib, which will be resampled by *lut*. The default, None, means :rc:`image.cmap`. lut : int or None, default: None If *name* is not already a Colormap instance and *lut* is not None, the colormap will be resampled to have *lut* entries in the lookup table. """ if name is None: name = mpl.rcParams['image.cmap'] if isinstance(name, colors.Colormap): return name _api.check_in_list(sorted(_cmap_registry), name=name) if lut is None: return _cmap_registry[name] else: return _cmap_registry[name]._resample(lut) File: /usr/lib/python3.9/site-packages/matplotlib/cm.py Type: function
para definir el espacio de colores, interpolamos 128 puntos entre los elementos de la paleta.
completo = []
npaleta = [[0,0,0.5, 0.7],[0,0.5,0, 0.7], [0.5,0,0,0.7]]
parte1 = np.linspace(start=npaleta[0], stop=npaleta[1],num=128)
parte2 = np.linspace(start=npaleta[1], stop=npaleta[2],num=128)
completo = np.append(parte1, parte2, 0)
clrs = ListedColormap(completo)
def pinta(u,v): return (1+cos(u+v))/2
S = parametric_plot3d(2*d+0.5*r, (u, -pi, pi),(v,-pi, pi),
color=(pinta,clrs),
plot_points=[120,120])
S.show()
Podríamos definir una curva paramétrizada por $t$ sobre esta superficie $$ u= \frac{t}{2} \qquad v = 3t$$
t = var('t')
p= (2*d+r/2)(u=t/2, v= 3*t)
show(p)
p= (2*d+r/1.9)(u=t/2, v= 3*t) # para que no se oculte dentro de la superficie
C = parametric_plot3d(p, (t, -pi, pi), thickness='3.0')
C
show(C+S)
Inclusive podríamos dibujar un campo sobre esa curva
E.<x,y,z> = EuclideanSpace()
p= (2*d+r/2)(u=t/2, v= 3*t)
T_p = E.vector_field(p.diff(t),name='T_p')
F_r = E.vector_field(r(u=t/2, v=3*t))
N_p = T_p.cross(F_r)
show(T_p[:])
show(F_r[:])
C = E.curve([*p],t)
nC = N_p.along(C)
GN = nC.plot(E.cartesian_coordinates(), ranges={t: (-pi, pi)}, number_values= 21)
GN
GC = C.plot(prange=(-pi, pi))
GC
(GN+GC).show()
Se pueden dar cuenta de que esta página no es interactiva. Y le faltan muchas explicaciones. Pero todo lo necesario lo podrán encontrar en los manuales de sagemath
Si desean probar experimentando, pueden bajar la hoja a sus propias computadoras de esta dirección
Primero: es genial tener una herramienta libre tan completa y poderosa. Como está hecho en python, se pueden hacer programas muy fácil y usar todo el poder expresivo de ese lenguaje, inclusive con sus idioms y detalles mas oscuros (a veces de hecho no hay de otra).
Pero ya dicho esto, es necesario reconocer que le falta mucho aún para ser fácil de usar. Sobre todo por que el concepto es un poco complicado de entender o no está completamente pulido o no existe realmente. Me explico: SageMath es la unión de muchisimas piezas independientes de código abierto completamente separadas, cada una con su propia historia y sus muy particulares condiciones tecnológicas y temporales. No me ha quedado claro cómo se puede empezar a usarlo o para qué, pues cada intento de hacer algo de matemáticas con él, deriva en una historia y concepción completamente distinta que en otros intentos de usarlo. Es decir: cuando lo exploré para hacer polinomios, los conceptos para entender su uso fueron completamente diferentes que cuando intenté usarlo para hacer teoría de números y también completamente distintos que cuando intenté hacer geometría. Inclusive dentro de la geometría, hacer cálculos sobre superficies es completamente distinto que dibujar sobre las mismas. Esto puede ser muy confuso a veces pero al final me parece que vale mucho la pena. No lo recomendaría a cualquier persona, solo tal vez a científicos muy propensos a programar y explorar en lugares que no se ha hecho mucho antes.
Lo mas recomendable es siempre buscar en los foros de preguntas relacionadas con lo que uno piensa hacer, leer algunos conceptos de la documentación y/o en artículos del Arxiv.